#ifndef IHD44780_H
#define IHD44780_H

#include <AnalyzerHelpers.h>
#include <SimulationChannelDescriptor.h>
#include <string>
#include <vector>

class HD44780AnalyzerSettings;
class SimulationChannelDescriptorGroup;
class IHD44780;

/* Represents a HD4480 interface capable of generating commands for a predefined number of communication lines */
class IHD44780
{
public:
    virtual ~IHD44780() { }

    enum Commands {CMD_NOOP = 0x00, CMD_CLEARDISPLAY = 0x01, CMD_RETURNHOME = 0X02, CMD_ENTRYMODE = 0x04, CMD_DISPLAYCONTROL = 0x08, CMD_SHIFT = 0X10, CMD_FUNCTION = 0X20, 
        CMD_CGRAM = 0X40, CMD_DDRAM = 0x80 };

    enum MoveDirection { CURSOR_DECREMENT = 0, CURSOR_INCREMENT = 0x02 };
    enum DisplayShift { DONOT_SHIFT_DISPLAY = 0, DO_SHIFT_DISPLAY = 0x01 };
    enum DisplayState { DISPLAY_OFF = 0, DISPLAY_ON = 0x04 };
    enum CursorState { CURSOR_OFF = 0, CURSOR_ON = 0x02 };
    enum BlinkingState { BLINKING_OFF = 0, BLINKING_ON = 0x01 };
    enum ScreenShiftState { MOVE_CURSOR = 0, SHIFT_DISPLAY = 0x08 };
    enum ShiftDirection { SHIFT_LEFT = 0, SHIFT_RIGHT = 0x04 };
    enum DataLength { INTERFACE_BITS4 = 0, INTERFACE_BITS8 = 0x10 };
    enum DataLines { DISPLAY_LINES1 = 0, DISPLAY_LINES2 = 0x08 };
    enum ScreenFont { FONT5X8 = 0, FONT5X10 = 0x04 };

    static void Init(  U32  SimulationSampleRateHz , HD44780AnalyzerSettings* Settings , std::vector< SimulationChannelDescriptor* >* Data, SimulationChannelDescriptorGroup* SimulationData );
    virtual void NoOperation();
    virtual void ClearDisplay();
    virtual void ReturnHome();
    virtual void EntryMode( MoveDirection CursorMode, DisplayShift DisplayMode);
    virtual void Display( DisplayState Display, CursorState Cursor, BlinkingState Blink );
    virtual void Shift( ScreenShiftState ShiftState, ShiftDirection Direction );
    virtual void Mode( DataLength Length, DataLines Lines, ScreenFont Font );
    virtual void SetCGRAMAddress( unsigned char Address );
    virtual void SetDDRAMAddress( unsigned char Address );
    virtual void CheckBusyFlagAsLoop(); 
    virtual void CheckBusyFlagAsPulse();
    virtual void CheckBusyFlagAsDelay();
    virtual void WaitInMillis( double TimeToWait );
    virtual void WaitInMicros( double TimeToWait );
    virtual void WaitInNanos( double TimeToWait );
    virtual void WriteString( char* Data ); 

protected: 
    IHD44780()    {}
    virtual void SendCommand( U8 Command );
    virtual void SendData( U8 Data );
    virtual void SetControlForData();
    virtual void SetControlForCommand();
    virtual void SetControlForBusyFlag();
    virtual void SetControlLow();
    virtual void SetDataLines( U8 Data ) = 0;
    virtual void PulseEnableLine();

protected:
    static HD44780AnalyzerSettings*                mSettings;
    static std::vector< SimulationChannelDescriptor* >*    mData;
    static SimulationChannelDescriptorGroup*               mSimulationData;
    static ClockGenerator                                  mClockGenerator;

    static const double TIME_AS;
    static const double TIME_ER;  
    static const double TIME_PWEH;
    static const double TIME_H;
    static const double TIME_YCE;
    static const double TIME_DDR;
};

#endif